Skip to content

Track failed playback commands with bounded retry backoff#259

Merged
Gudsfile merged 5 commits into
mainfrom
bug/playback-failure-session-state
May 20, 2026
Merged

Track failed playback commands with bounded retry backoff#259
Gudsfile merged 5 commits into
mainfrom
bug/playback-failure-session-state

Conversation

@msgerbush
Copy link
Copy Markdown
Collaborator

Summary

This is the first PR in the Sonos stale-IP recovery stack (refs #258). The original issue was triggered when the selected Sonos speaker changed LAN IPs, leaving the running process with a stale SoCo connection. A later pause() call then failed with No route to host.

This PR does not re-resolve stale Sonos speakers yet. Instead, it makes playback command failures safe in the domain state machine:

  • Add PlaybackCommandRetry to PlaybackSession
  • Only update session state after play, resume, pause, or stop succeeds
  • Retry failed playback commands with bounded backoff instead of every loop tick
  • Preserve retry state across brief missed tag reads
  • Avoid setting paused_at when pause() did not actually pause playback

Behavior

When a playback command raises PlaybackError, the session now records retry metadata and leaves the logical playback state unchanged. Matching actions are retried after backoff; unrelated actions can clear or replace the retry state.

This prevents failed commands from making the app believe Sonos changed state when it did not.

Notes

@msgerbush msgerbush force-pushed the bug/playback-failure-session-state branch from 1a14385 to c670ac5 Compare May 19, 2026 03:03
Copy link
Copy Markdown
Owner

@Gudsfile Gudsfile left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two minor suggestions, otherwise looks good to me!

Comment thread jukebox/domain/use_cases/handle_tag_event.py Outdated
Comment thread jukebox/domain/use_cases/handle_tag_event.py Outdated
@Gudsfile Gudsfile merged commit 358a6f1 into main May 20, 2026
6 checks passed
@Gudsfile Gudsfile deleted the bug/playback-failure-session-state branch May 20, 2026 20:02
@msgerbush
Copy link
Copy Markdown
Collaborator Author

I agree, I was also a little uneasy about introducing this new text field without better validation. I went ahead and added the tag separately and simplified the conditional. I added some validation to constrain the legitimate tag cases for now, but I could see us expanding those in the future.

Gudsfile added a commit that referenced this pull request May 21, 2026
## Summary

Fixes #258 

Depends on #259 

This PR completes recovery for the stale Sonos host issue. In the
reported failure, jukebox held onto a SoCo object for `Living Room` at
`192.168.1.24` after the speaker moved to `192.168.1.25`. A later
`pause()` attempted to contact the old host and failed with `No route to
host`.

This change adds Sonos adapter recovery for transport failures. When
`play`, `pause`, `resume`, or `stop` fails because the current Sonos
object is unreachable, the adapter re-resolves the saved playback
target, switches to the newly resolved coordinator host, rebuilds the
ShareLink plugin, and retries the command once.

## Changes

- Add `SonosPlaybackTarget` and `SonosPlaybackTargetResolver` as the
recovery boundary.
- Teach `DefaultSonosService` to resolve a playback target back into a
runtime Sonos group.
- Wire the playback target resolver through `build_jukebox()`.
- Cache the speaker name from `get_speaker_info()` so command logging
does not trigger a networked `player_name` lookup.
- Replace the old UPnP decorator with shared command execution that
handles recovery while preserving known UPnP error logging.
- Add coverage for stale-IP recovery, failed recovery, DI wiring,
playback target resolution, and UPnP error handling.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants